<?php
declare(strict_types=1);

namespace App\Service;
use App\Constants\StrStatus;
use App\Constants\XZXResponseCode;
use App\Exception\XZXValidationException;
use App\Model\Dao\ChannelCollectionDao;
use App\Model\Dao\ChannelCollectionMchConnDao;
use App\Model\Dao\ChannelMchConnLogDao;
use App\Model\Dao\MchAccountDao;
use App\Model\Dao\MchConfigLogDao;
use App\Model\Dao\MchInfoLogDao;
use App\Model\Dao\MchSysAdminDao;
use App\Model\Dao\MchConfigDao;
use App\Model\Dao\MchInfoDao;
use App\Model\Dao\MchTagConnDao;
use App\Model\Dao\MchRegEmailChangeApplyDao;
use App\Model\Dao\RateCustomizedDao;
use App\Model\Dao\MchTagDao;
use App\Model\Dao\MchTradeWebsiteDao;
use App\Model\Dao\RateSettleDao;
use App\Model\Dao\RiskRuleCollectionDao;
use App\Model\Dao\RiskRuleMchRefDao;
use App\Model\Dao\SysAdminDao;
use App\Model\Dao\SysAdminMchRelationDao;
use App\Model\Enum\CommonReviewStatusEnum;
use App\Model\Enum\MchInfoRegStatusEnum;
use App\Model\Enum\MchInfoStatusEnum;
use App\Model\Enum\OrderTransStatusEnum;
use App\Utils\CustomUtils;
use App\Utils\DateUtils;
use App\Utils\RedisUtils;
use App\Utils\StringUtils;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Redis\Redis;
use Hyperf\Utils\Codec\Json;
use App\Utils\OpenService;
use App\Service\EmailService;
use App\Service\CommonBankService;
use App\Service\CommonService;

class MchInfoService
{

    /**
     * @Inject()
     * @var CommonService
     */
    private $CommonService;

    /**
     * @Inject()
     * @var MchRegEmailChangeApplyDao
     */
    private $MchRegEmailChangeApplyDao;

    /**
     * @Inject()
     * @var RateCustomizedDao
     */
    private $RateCustomizedDao;

    /**
     * @Inject()
     * @var MchSysAdminDao
     */
    private $MchSysAdminDao;

    /**
     * @Inject()
     * @var SysAdminMchRelationDao
     */
    private $SysAdminMchRelationDao;

    /**
     * @Inject()
     * @var SysAdminDao
     */
    private $SysAdminDao;

    /**
     * @Inject()
     * @var EmailService
     */
    private $EmailService;

    /**
     * @Inject()
     * @var MchInfoDao
     */
    private $MchInfoDao;

    /**
     * @Inject()
     * @var MchAccountDao
     */
    private $MchAccountDao;

    /**
     * @Inject()
     * @var EmailCheckService
     */
    private $EmailCheckService;

    /**
     * @Inject()
     * @var MchSysAdminService
     */
    private $MchSysAdminService;

    /**
     * @Inject()
     * @var MchSysRoleService
     */
    private $MchSysRoleService;

    /**
     * @Inject()
     * @var CommonBankService
     */
    private $CommonBankService;

    /**
     * @Inject()
     * @var CommonRiskService
     */
    private $CommonRiskService;

    /**
     * @Inject()
     * @var MchTradeWebsiteDao
     */
    private $MchTradeWebsiteDao;

    /**
     * @Inject()
     * @var MchConfigDao
     */
    private $MchConfigDao;

    /**
     * @Inject()
     * @var MchTagConnDao
     */
    private $MchTagConnDao;

    /**
     * @Inject()
     * @var RateSettleDao
     */
    private $RateSettleDao;

    /**
     * @Inject()
     * @var ChannelCollectionMchConnDao
     */
    private $ChannelCollectionMchConnDao;

    /**
     * @Inject()
     * @var RiskRuleMchRefDao
     */
    private $RiskRuleMchRefDao;

    /**
     * @Inject()
     * @var RiskRuleCollectionDao
     */
    private $RiskRuleCollectionDao;

    /**
     * @Inject()
     * @var ChannelCollectionDao
     */
    private $ChannelCollectionDao;

    /**
     * @Inject()
     * @var MchInfoLogDao
     */
    private $MchInfoLogDao;

    /**
     * @Inject()
     * @var MchConfigLogDao
     */
    private $MchConfigLogDao;

    /**
     * @Inject()
     * @var ChannelMchConnLogDao
     */
    private $ChannelMchConnLogDao;

    /**
     * @param $param
     * @return array
     * 查看
     */
    public function get($param)
    {
        $result = $this->MchInfoDao->get($param['id']);
        if (!$result) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }

        (isset($result['createTime']) && !empty($result['createTime'])) && $result['createTime'] = DateUtils::getDateTime($result['createTime']);
        (isset($result['reviewTime']) && !empty($result['reviewTime'])) && $result['reviewTime'] = DateUtils::getDateTime($result['reviewTime']);

        $tradeWebsite = $this->MchTradeWebsiteDao->get($result['tradeWebsiteId']);
        if (!empty($tradeWebsite)) {
            $result['url'] = $tradeWebsite['url'];
        } else {
            $result['url'] = '';
        }

        $result['fieldStatus'] = json::decode($result['fieldStatus'],true);

        $result['strStatus'] = MchInfoStatusEnum::getLabel($result['status']);
        $result['strApiStatus'] = MchInfoStatusEnum::getLabel($result['apiStatus']);
        $result['strRegStatus'] = MchInfoRegStatusEnum::getLabel($result['regStatus']);
        $result['strLoginStatus'] = MchInfoStatusEnum::getLabel($result['loginStatus']);

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$result);
    }

    /**
     * @param $param
     * @return array
     * 获取配置，各种状态，通道配置等
     */
    public function getConfig($param) {
        $info = $this->MchInfoDao->get($param['mchId']);
        if (!$info) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }

        if($info['regStatus'] != 1){
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::MCH_REG_STATUS_NO_PASS));
        }

        // 配置信息
        $config = $this->MchConfigDao->getByMchId($param['mchId']);
        $result = [];
        if (empty($config)) {
            $result = [
                'mchId'                => $info['id'],
                'mchNo'                => $info['mchNo'],
                'channelCollection'    => [],
                'settleRateId'         => '',
                'settleExchangeRateId' => '',
                'riskId'               => '',
                'settleCurrency'       => '',
                'transCurrency'        => '',
            ];
        } else {
            $result = [
                'mchId'                => $config['mchId'],
                'mchNo'                => $config['mchNo'],
                'settleRateId'         => $config['settleRateId'],
                'settleExchangeRateId' => $config['settleExchangeRateId'],
                'settleCurrency'       => $config['settleCurrency'],
                'transCurrency'        => $config['transCurrency'],
            ];
        }

        // 网关通道集合
        $channelCollectionMchConn = $this->ChannelCollectionMchConnDao->getByMchNo($config['mchNo']);
        $channelCollectionMchConn = array_map(function ($item) {
            return [
                'id' => $item['collectionId'],
                'payType' => $item['payType'],
            ];
        }, $channelCollectionMchConn);
        $result['channelCollection'] = $channelCollectionMchConn;

        // 风控id
        $riskRuleMchRef = $this->RiskRuleMchRefDao->getByMchNo($config['mchNo']);
        $result['riskId'] = empty($riskRuleMchRef) ? "" : $riskRuleMchRef['collectionId'];

        // 标签
        $mchTagConn = $this->MchTagConnDao->getByMchId($param['mchId']);

        $result['mchName'] = $info['mchName'];
        $result['appId'] = $info['appId'];
        $result['appSecret'] = $info['appSecret'];
        $result['salesId'] = $info['salesId'];
        $result['mchTagId'] = empty($mchTagConn) ? '' : array_column($mchTagConn, 'mchTagId');
        $result['apiStatus'] = $info['apiStatus'];
        $result['regStatus'] = $info['regStatus'];
        $result['loginStatus'] = $info['loginStatus'];

        // 结算费率
        $rateResult = $this->RateSettleDao->getByMchId($param['mchId']);
        if (!empty($rateResult)) {
            $rateData = [
                'minWithdrawAmount' => $rateResult['minWithdrawAmount'],
                'maxWithdrawAmount' => $rateResult['maxWithdrawAmount'],
                'minTransAmount'    => $rateResult['minTransAmount'],
                'maxTransAmount'    => $rateResult['maxTransAmount'],
                'transPerFee'       => $rateResult['transPerFee'],
                'withdrawPerFee'    => $rateResult['withdrawPerFee'],
            ];
        } else {
            $rateData = [];
        }
        $result['rateSettle'] = $rateData;

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE), $result);
    }

    /**
     * @param $param
     * @return array
     * 设置配置
     */
    public function editConfig($param) {
        $info = $this->MchInfoDao->get($param['mchId']);
        if (!$info) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::NO_RISK_COLLECTION));
        }

        if($info['regStatus'] != 1){
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::MCH_REG_STATUS_NO_PASS));
        }

        if ($param['riskId']) {
            $riskCollection = $this->RiskRuleCollectionDao->get($param['riskId']);
            if (!$riskCollection || $riskCollection['type'] != 2) {
                throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::NOT_VALID_RISK_COLLECTION));
            }
        }

        if (!empty($param['channelCollection'])) {
            foreach ($param['channelCollection'] as $value) {
                if (empty($value['id'])) {
                    throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::NO_CHANNEL_COLLECTION));
                }
                $channelCollection = $this->ChannelCollectionDao->get($value['id']);
                if (!$channelCollection || $channelCollection['payType'] != $value['payType']) {
                    throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::NO_CHANNEL_COLLECTION));
                }
            }
        }

        Db::beginTransaction();

        try {
            // 更新商户
            $updateMch = [
                'mchName'     => $param['mchName'],
                'salesId'     => $param['salesId'],
                'apiStatus'   => $param['apiStatus'],
                // 'regStatus'   => $param['regStatus'], 注册状态应该只能在审核的时候修改
                'loginStatus' => $param['loginStatus'],
                'updateBy'    => $param['updateBy'],
            ];
            $this->MchInfoDao->update($param['mchId'], $updateMch);

            // 删除用户-商户关联，同时删除该该销售原来上级-商户关联
            if ($param['salesId'] != $info['salesId']) {
                $oldSales = $this->SysAdminDao->get($info['salesId']);
                $this->SysAdminMchRelationDao->delWhere(['adminId' => $info['salesId'], 'mchId' => $info['id']]);
                $this->SysAdminMchRelationDao->delWhere(['adminId' => $oldSales['parentId'], 'mchId' => $info['id']]);

                // 新增用户-商户关联，新增
                if (!empty($param['salesId']) ) {
                    $newSales = $this->SysAdminDao->get($param['salesId']);
                    $this->SysAdminMchRelationDao->add([
                        'id'            => CustomUtils::createUUID(),
                        'adminId'       => $param['salesId'],
                        'mchId'         => $info['id'],
                        'status'        => 1,
                        'createTime'    => time()
                    ]);
                    $this->SysAdminMchRelationDao->add([
                        'id'            => CustomUtils::createUUID(),
                        'adminId'       => $newSales['parentId'],
                        'mchId'         => $info['id'],
                        'status'        => 1,
                        'createTime'    => time()
                    ]);
                }
            }

            // 更新配置
            $config = $this->MchConfigDao->getByMchId($param['mchId']);
            $updateConfig = [
                'settleRateId'         => $param['settleRateId'],
                'settleExchangeRateId' => $param['settleExchangeRateId'],
                'settleCurrency'       => $param['settleCurrency'],
                'transCurrency'        => $param['transCurrency'],
                'updateBy'             => $param['updateBy'],
            ];
            CustomUtils::xzxDebug($config);

            if (!!$config) {
                // 更新
                $this->MchConfigDao->update($config['id'], $updateConfig);
            } else {
                // 新增
                $updateConfig['id'] = CustomUtils::createUUID();
                $updateConfig['mchId'] = $info['id'];
                $updateConfig['mchNo'] = $info['mchNo'];
                $updateConfig['status'] = 1;
                $updateConfig['createBy'] = $param['createBy'];
                $updateConfig['createTime'] = time();
                $updateConfig['updateBy'] = $param['createBy'];
                $this->MchConfigDao->add($updateConfig);
                $config = $this->MchConfigDao->getByMchId($param['mchId']);
            }

            // 删除标签
            $this->MchTagConnDao->delWhere(['mchId' => $param['mchId']]);

            // 更新标签
            $mchTagId = $param['mchTagId'];
            $mchTagData = [];
            foreach ($mchTagId as $value) {
                array_push($mchTagData, [
                    "id"            => CustomUtils::createUUID(),
                    "mchId"         => $info['id'],
                    "mchNo"         => $info['mchNo'],
                    "mchTagId"      => $value,
                    "status"        => 1,
                    "createTime"    => time(),
                ]);
            }
            $this->MchTagConnDao->add($mchTagData);

            // 更新风控
            $riskRuleMchRef = $this->RiskRuleMchRefDao->getByMchNo($config['mchNo']);
            $oldRiskId = empty($riskRuleMchRef) ? "" : $riskRuleMchRef['collectionId'];
            if ($param['riskId'] != $oldRiskId) {
                $result = $this->CommonRiskService->riskRuleMchRefSetBind([
                    'mchNo' => $config['mchNo'],
                    'type' => 1,
                    'collectionId' => $param['riskId']
                ]);
                if ($result['code'] != XZXResponseCode::SUCCESS_CODE) {
                    throw new XZXValidationException($result['message']);
                }
            }

            // 更新网关集合
            $settleCurrencyList = [];
            foreach ($param['channelCollection'] as $value) {
                $result = $this->CommonBankService->channelCollectionMchConn(['mchNo' => $config['mchNo'], 'payType' => $value['payType'], 'collectionId' => $value['id']]);
                if ($result['code'] != XZXResponseCode::SUCCESS_CODE) {
                    throw new XZXValidationException($result['message']);
                }

                $settleCurrencyResult = $this->CommonBankService->channelCollectionSettleCurrencyList(['id' => $value['id']]);
                if ($settleCurrencyResult['code'] != XZXResponseCode::SUCCESS_CODE) {
                    throw new XZXValidationException($settleCurrencyResult['message']);
                }
                $tmp = $settleCurrencyResult['data']['list'];
                foreach($tmp as $v){
                    array_push($settleCurrencyList,$v['code']);
                }
            }
            CustomUtils::xzxDebug("========Start");
            CustomUtils::xzxDebug($settleCurrencyList);

            //分割 transCurrency
            $transCurrencyList = explode(",",$param['transCurrency']);
            CustomUtils::xzxDebug($transCurrencyList);
            CustomUtils::xzxDebug("========End");
            foreach($transCurrencyList as $v){
                //交易币种 ： 交易币种  交易类型
                $queryParam = array(
                    'rateGroupId'    => $param['settleExchangeRateId'],
                    'sourceCurrency' => $v,
                    'targetCurrency' => $v,
                    'type'           => 1
                );
                if(!$this->RateCustomizedDao->getWhere($queryParam))
                {
                    throw new XZXValidationException($v.'->'.$v.'的交易类型汇率记录没设置');
                }
                //交易币种 ： 商户结算币种  结算类型
                $queryParam = array(
                    'rateGroupId'    => $param['settleExchangeRateId'],
                    'sourceCurrency' => $v,
                    'targetCurrency' => $param['settleCurrency'],
                    'type'           => 2
                );
                if(!$this->RateCustomizedDao->getWhere($queryParam))
                {
                    throw new XZXValidationException($v.'->'.$param['settleCurrency'].'的结算类型汇率记录没设置');
                }

                //交易币种 ： 网关结算币种  结算类型
                foreach($settleCurrencyList as $vv){
                    $queryParam = array(
                        'rateGroupId'    => $param['settleExchangeRateId'],
                        'sourceCurrency' => $v,
                        'targetCurrency' => $vv,
                        'type'           => 2
                    );
                    if(!$this->RateCustomizedDao->getWhere($queryParam))
                    {
                        throw new XZXValidationException($v.'->'.$vv.'的结算类型汇率记录没设置');
                    }
                }
                
            }
        } catch (\Throwable $th) {
            CustomUtils::xzxDebug($th->getMessage());
            Db::rollBack();
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::EDIT_FAIL)." ".$th->getMessage());
        }
        Db::commit();

        // 写log
        $config = $this->MchConfigDao->getByMchId($param['mchId']);
        $log = $config;
        $log['id'] = CustomUtils::createUUID();
        $log['createTime'] = time();
        $this->MchConfigLogDao->add($log);

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE), "");
    }

    /**
     * @param $param
     * @return array
     * 删除
     */
    public function del($param)
    {
        $result = $this->MchInfoDao->get($param['id']);
        if (!$result) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }
        try {
            $this->MchInfoDao->del($param['id'],false);
        } catch (\Throwable $th) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DEL_FAIL));
        }
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),CustomUtils::xzxEmptyObject());
    }

    /**
     * @param $param
     * @return array
     * 新增
     */
    public function add($param)
    {

        // 检查email抢注
        $isMch = $this->MchInfoDao->getByEmail($param['email']);
        if ($isMch) {
            // throw new XZXValidationException("email {$param['email']} 已抢注");
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::OCCUPIED_EMAIL));
        }

        $data = $param;
        $data['fieldStatus'] = json::encode($param['fieldStatus']);
        $data['id'] = CustomUtils::createUUID();
        $data['status'] = 0;
        $data['apiStatus'] = 0;
        $data['regStatus'] = 0;
        $data['editStatus'] = 0;
        $data['loginStatus'] = 1;
        $data['reviewTime'] = 0;
        $data['createTime'] = time();
        $data['updateBy']   = $param['createBy'];
        // 生成appid, appsecret
        $data['appId'] = CustomUtils::createAppId();
        $data['appSecret'] = CustomUtils::createAppSecret();
        isset($param['remark']) && $data['remark'] = $param['remark'];
        isset($param['officeCert']) && $data['officeCert'] = $param['officeCert'];
        isset($param['nar']) && $data['nar'] = $param['nar'];
        isset($param['corporation25PercentCert']) && $data['corporation25PercentCert'] = $param['corporation25PercentCert'];
        isset($param['corporation25PercentAddrCert']) && $data['corporation25PercentAddrCert'] = $param['corporation25PercentAddrCert'];
        isset($param['enCompanyStructure']) && $data['enCompanyStructure'] = $param['enCompanyStructure'];

        if ($param['source'] == 1) {
            // 商户提交注册需要验证码
            $this->EmailCheckService->check(['email' => $param['email'], 'code' => $param['code'], 'type' => 1]);
            unset($data['code']);
        } else {
            // 后台添加，状态全部正常
            $data['status'] = 1;
            $data['apiStatus'] = 1;
            $data['regStatus'] = 1;
            $data['loginStatus'] = 1;
            $data['editStatus'] = 1;
        }

        // 终端号顺序生成
        $last = $this->MchInfoDao->getLast();
        if (empty($last)) {
            $data['mchNo'] = 'M0001';
        } else {
            $lastMchNo = $last['mchNo'];
            $lastMchNo = str_replace('M', '', $lastMchNo);
            $lastMchNo = intval($lastMchNo);
            $lastMchNo += 1;
            $data['mchNo'] = 'M' . sprintf("%04d", $lastMchNo);
        }

        Db::beginTransaction();

        try {
            // 新增商户网站
            $tradeWebsite = [
                'id'           => CustomUtils::createUUID(),
                'mchId'        => $data['id'],
                'mchNo'        => $data['mchNo'],
                'url'          => $param['url'],
                'beianNo'      => isset($param['beianNo']) ? $param['beianNo'] : '',
                'status'       => 1,
                'remark'       => '',
                'source'       => $param['source'],
                'reviewStatus' => $param['source'] == 1 ? 0 : 1,
                'reviewTime'   => $param['source'] == 1 ? null : time(),
                'reviewBy'     => $param['source'] == 1 ? null : $param['createBy'],
                'createTime'   => time(),
                'createBy'     => $param['createBy'],
                'updateBy'     => $param['createBy'],
            ];
            $this->MchTradeWebsiteDao->insert($tradeWebsite);

            // 新增商户
            unset($data['url']);
            unset($data['beianNo']);
            $this->MchInfoDao->insert($data);

            // 新增商户超管角色
            $roleRet = $this->MchSysRoleService->add([
                'mchId'     => $data['id'],
                'type'      => 1,
                'name'      => 'root',
                'remark'    => 'Super Administrator',
                'createBy'  => $param['createBy']
            ]);
            $roleId = $roleRet['data'];

            // todo 新增管理员
            $sysAdminInitPassword = OpenService::getNonceStr(6);
            $sysAdminInfo = $this->MchSysAdminService->doAdd([
                'mchId'         => $data['id'],
//                'password'    => NumberUtils::random(8),
                'nick'          => 'admin',
                'realName'      => 'admin',
                'password'      => $sysAdminInitPassword,
                'username'      => 'admin',
                'email'         => $data['email'],
                'needChangePwd' => 1,
                'roleId'        => $roleId,
                'status'        => 1,
                'createBy'      => $param['createBy']
            ]);

            $googleAuthSecret = $sysAdminInfo['data']['googleAuthSecret'];

            // 更新商户的交易网站
            $updateMch = [
                'tradeWebsiteId'    => $tradeWebsite['id']
            ];
            $this->MchInfoDao->update($data['id'], $updateMch);

            // 新增商户账户
            $mchAccount = [
                "id"            => CustomUtils::createUUID(),
                "mchId"         => $data['id'],
                "mchNo"         => $data['mchNo'],
                "createTime"    => time(),
                "createBy"      => $param['createBy']
            ];
            $this->MchAccountDao->add($mchAccount);

            

        } catch (\Throwable $th) {
            Db::rollBack();
            CustomUtils::xzxDebug($th->getMessage());
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::ADD_FAIL));
        }

        Db::commit();

        // todo 发送邮件
        $sendMailParam = array(
            'type'             => 13,
            'email'            => $data['email'],
            'username'         => 'admin',
            'password'         => $sysAdminInitPassword,
            'googleAuthSecret' => $googleAuthSecret
        );
        CustomUtils::xzxDebug($sendMailParam);
        $this->EmailService->addMq($sendMailParam);

        $sendMailParam = array(
            'type'  => 16,
            'email' => env('NOTIFY_EMAIL'),
            "mchNo" => $data['mchNo'],
        );
        CustomUtils::xzxDebug($sendMailParam);
        $this->EmailService->addMq($sendMailParam);

        $ret = [
            'username'  => 'admin',
            'mchNo'     => $data['mchNo']
        ];

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE), $ret);
    }

    public function changeRegEmail($param)
    {
        $user = $this->MchSysAdminDao->get($param['uid']);
        if (!$user) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }


        $info = $this->MchInfoDao->get($param['mchId']);
        if (!$info) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }
        $id = $param['mchId'];
        $data = array();
        // 检查是不是被别人抢注了
        $isMch = $this->MchInfoDao->getByEmail($param['email']);
        if ($isMch) {
            // throw new XZXValidationException("{$param['email']}已被使用，请更换其他邮箱");
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::OCCUPIED_EMAIL));

        }

        $queryParam = array(
            'mchId'    => $param['mchId'],
            'oldEmail' => $info['email'],
            'reviewStatus' => 0, //待审核
        );
        $applyInfo = $this->MchRegEmailChangeApplyDao->getWhere($queryParam);
        if($applyInfo ){
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::OCCUPIED_EMAIL));
        }

        $this->EmailCheckService->check(['email' => $param['email'], 'code' => $param['code'], 'type' => 2]);
        if(!config("isDev")){
            // 验证码验证
            $verifyRet = $this->CommonService->checkGoogleCode($user['googleAuthSecret'], strval($param['googleCode']));
            if ($verifyRet['googleCode']) {
                throw new XZXValidationException($verifyRet['message']);
            }
        }

        // $data['email'] = $param['email'];
        $data = array(
            'id'         => CustomUtils::createUUID(),
            'mchId'      => $param['mchId'],
            'mchNo'      => $info['mchNo'],
            'oldEmail'   => $info['email'],
            'newEmail'   => $param['email'],
            'source'     => 1,
            "createTime" => time(),
            "createBy"   => $param['createBy']
        );

        try {
            // $this->MchInfoDao->update($id, $data);
            $this->MchRegEmailChangeApplyDao->insert($data);
            

        } catch (\Throwable $th) {
            CustomUtils::xzxDebug($th->getMessage());
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::EDIT_FAIL));
        }
        //send mail to nodify email
        $sendMailParam = array(
            'type'  => 18,
            'email' => env('NOTIFY_EMAIL'),
            "mchNo" => $data['mchNo'],
        );
        CustomUtils::xzxDebug($sendMailParam);
        $this->EmailService->addMq($sendMailParam);

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),CustomUtils::xzxEmptyObject());

    }

    /**
     * @param $param
     * @return array
     * 修改
     */
    public function edit($param)
    {
        $info = $this->MchInfoDao->get($param['id']);
        if (!$info) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }

        $id = $param['id'];
        $data = array();

        if ($param['source'] == 2) {
            // 后台更新直接更新字段
            foreach($param as $k => $v){
                if($k == "id" || $k == "url"  || $k == "beianNo"){
                    continue;
                }
                if(isset($v)){
                    $data[$k] = $v;
                }
            }
        } else {
            if(isset($param['email'])){
                // 检查是不是被别人抢注了
                $isMch = $this->MchInfoDao->getByEmail($param['email']);
                if ($isMch) {
                    throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::OCCUPIED_EMAIL));
                }

                $this->EmailCheckService->check(['email' => $param['email'], 'code' => $param['code'], 'type' => 2]);
            }

            if(isset($param['isReAuth'])){
                if($param['isReAuth'] == 1){
                    //检查商户注册状态是否是驳回，只有是驳回的才能进入这个流程
                    if($info['regStatus'] == 2){
                        //驳回修改后的再次提交审核 需要讲regStatus变更为待审核状态，以便进入审核流程
                        $data['regStatus'] = 0;
                    }
                }
            }

            // 如果是已经注册成功的修改，把editStatus置为0
            if ($info['regStatus'] == 1) {
                $data['editStatus'] = 0;
            }

            $data['fieldStatus'] = json::encode($param['fieldStatus']);

            foreach($param as $k => $v){
                if($k == "id" || $k == "url"  || $k == "beianNo" || $k == "isReAuth" || $k == "mchId"){
                    continue;
                }
                if($k == 'fieldStatus'){
                    $data[$k] = json::encode($v);
                    continue;
                }
                if(isset($v)){
                    $data[$k] = $v;
                }
            }
            
        }

        CustomUtils::xzxDebug($data);

        try {
            $this->MchInfoDao->update($id, $data);

            // 如果是商户提交，可能更新交易网站
            if ($param['source'] == 1) {
                // 查出交易网站
                $mchTradeWebsite = $this->MchTradeWebsiteDao->get($info['tradeWebsiteId']);
                // 审核交易网站
                if (!empty($mchTradeWebsite)) {
                    $updateTradeWebsite = [
                        'url'       => $param['url'],
                        'beianNo'   => isset($param['beianNo']) ? $param['beianNo'] : '',
                    ];
                    $this->MchTradeWebsiteDao->update($mchTradeWebsite['id'], $updateTradeWebsite);
                }
            }

        } catch (\Throwable $th) {
            CustomUtils::xzxDebug($th->getMessage());
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::EDIT_FAIL));
        }
        if ($param['source'] == 1) {
            //发邮件提醒管理员审核资料
            
            $sendMailParam = array(
                'type'  => 17,
                'email' => env('NOTIFY_EMAIL'),
                "mchNo" => $info['mchNo'],
            );
            CustomUtils::xzxDebug($sendMailParam);
            $this->EmailService->addMq($sendMailParam);
        }
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),CustomUtils::xzxEmptyObject());
    }

    /**
     * @param $param
     * @return array
     * 审核
     */
    public function auth($param) {
        $info = $this->MchInfoDao->get($param['id']);
        if (!$info) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }
        // 查出交易网站
        $mchTradeWebsite = $this->MchTradeWebsiteDao->get($info['tradeWebsiteId']);

        if($info['regStatus'] == 1)
        {
            //已经通过，不需要再审核
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::MCH_REG_STATUS_PASSED));
        }

        if($info['regStatus'] == 2)
        {
            //已经驳回，不需要再审核
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::MCH_REG_STATUS_REJECT));
        }

        if($info['regStatus'] == 3)
        {
            //已经禁用，不需要再审核
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::MCH_REG_STATUS_FORBIDDEN));
        }

        $id = $param['id'];
        $data = [
            'regStatus'  => $param['regStatus'],
            'regRemark'  => isset($param['regRemark']) ? $param['regRemark'] : ''
        ];
        if ($param['regStatus'] == 1) {
            // 审核通过
            $data['loginStatus'] = 1;
            $data['status']      = 1;
            $data['apiStatus']   =  1;
            $data['editStatus']   =  1;
        }
        // 审核失败的话，需要把失败的从fieldStatus取出来覆盖回去
        $fieldStatus = $param['fieldStatus'];

        $data['fieldStatus'] = json::encode($fieldStatus);
        $this->MchInfoDao->update($id, $data);

        // 审核交易网站
        if (!empty($mchTradeWebsite)) {
            $updateTradeWebsite = [
                'reviewStatus'  => ($param['regStatus'] == 1 ? 1 : 0)
            ];
            $this->MchTradeWebsiteDao->update($mchTradeWebsite['id'], $updateTradeWebsite);
        }

        // 写日志
        $this->addMchLog($param['id']);

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),CustomUtils::xzxEmptyObject());
    }

    public function reAuth($param) {
        $info = $this->MchInfoDao->get($param['id']);
        if (!$info) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }
        if ($info['regStatus'] != 1) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::MCH_REG_STATUS_NO_PASS));
        }

        $id = $param['id'];
        $fieldStatus = $param['fieldStatus'];

        $data['fieldStatus'] = json::encode($fieldStatus);
        $data['editStatus'] = $param['editStatus'];
        $data['editReviewRemark'] = isset($param['editReviewRemark']) ? $param['editReviewRemark'] : '';
        $this->MchInfoDao->update($id, $data);

        // 写日志
        $this->addMchLog($param['id']);

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),CustomUtils::xzxEmptyObject());
    }

    /**
     * @param array $param
     * @return array
     * 列表
     */
    public function list(array $param)
    {

        $limit = $param['limit'];
        $page = $param['page'];

        $total = $this->MchInfoDao->getCount($param);
        $list = $this->MchInfoDao->getList($param, $page, $limit);

        foreach ($list as $k => $v) {
            (isset($v['createTime']) && !empty($v['createTime'])) && $v['createTime'] = DateUtils::getDateTime($v['createTime']);
            $v['strStatus'] = MchInfoStatusEnum::getLabel($v['status']);
            $v['strApiStatus'] = MchInfoStatusEnum::getLabel($v['apiStatus']);
            $v['strRegStatus'] = MchInfoRegStatusEnum::getLabel($v['regStatus']);
            $v['strLoginStatus'] = MchInfoStatusEnum::getLabel($v['loginStatus']);
            $v['strEditStatus'] = CommonReviewStatusEnum::getLabel($v['editStatus']);
            $v['fieldStatus'] = json::decode($v['fieldStatus'],true);
            $list[$k] = $v;
        }

        $data = array(
            'total' => $total,
            'list' => $list
        );

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$data);
    }

    public function getOption(array $param) {
        $data = $this->MchInfoDao->getOption($param);
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$data);
    }

    public function addMchLog($id) {
        // 写log
        $info = $this->MchInfoDao->get($id);
        $log = $info;
        $log['id'] = CustomUtils::createUUID();
        $log['mchId'] = $id;
        $log['createTime'] = time();
        $this->MchInfoLogDao->add($log);
    }

    public function log($param) {
        $result = $this->MchInfoLogDao->getWhereList(['mchId' => $param['id']], ['createTime' => 'desc']);
        foreach ($result as $k => $v) {
            if(isset($v['createTime'])){
                $v['createTime'] = DateUtils::getDateTime($v['createTime']);
            }
            $result[$k] = $v;
        }
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$result);
    }

    public function configLog($param) {
        $result = $this->MchConfigLogDao->getWhereList(['mchId' => $param['id']], ['createTime' => 'desc']);
        foreach ($result as $k => $v) {
            if(isset($v['createTime'])){
                $v['createTime'] = DateUtils::getDateTime($v['createTime']);
            }
            $result[$k] = $v;
        }
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$result);
    }

    public function getChannelMchConnLogList($param) {
        $result = $this->ChannelMchConnLogDao->getByMchNo($param['mchNo']);
        foreach ($result as $k => $v) {
            if(isset($v['createTime'])){
                $v['createTime'] = DateUtils::getDateTime($v['createTime']);
            }
            $result[$k] = $v;
        }
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$result);
    }

}
